home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / type.cq / type.c
Encoding:
C/C++ Source or Header  |  1985-04-12  |  6.2 KB  |  284 lines

  1. static char *sccsid = "@(#)type.c       1.7u (UCF) 82/12/15";
  2. /*
  3.  * TYPE - types regular or squeezed files
  4.  *
  5.  * Compile as follows:
  6.  *      cc [-DVAX] -O type.c -o type
  7.  *         (define VAX only if running on VAX)
  8.  *
  9.   Derived from cnode 'cat', typesq, and others. W. Earnest 5/28/82
  10.   Credit to the following and others for parts of the software:
  11. Dick Greenlaw(usq)
  12. Bob Mathias(typesq)
  13. Steve Passe(cnode)
  14. Joe Shannon(cnode)
  15. Chuck Forsberg (Unix version)
  16.  
  17. Type recognizes CPMEOF (0x1A) on all files.  A header line is printed
  18. for each file.  If the last text character of a file is not linefeed,
  19. one is output before the header line for the next file.  If the file is
  20. squeezed, the original filename is printed.  Quit causes type to
  21. advance to the next file.
  22.  
  23. */
  24.  
  25. #include <stdio.h>
  26. #include <signal.h>
  27. #define ERROR (-1)
  28. #define OK 0
  29. #define CPMEOF 0x1A
  30. #define PATHLEN 128
  31.  
  32. #define RECOGNIZE 0xFF76/* unlikely pattern */
  33. #define DLE 0x90/* repeat byte flag */
  34. #define SPEOF 256/* special endfile token */
  35. #define NUMVALS 257/* 256 data values plus SPEOF*/
  36. #define LARGE 30000
  37.  
  38. #ifdef VAX/*  simulate 16-bit integers and define type for uniformity */
  39. typedef short INT;
  40. #else/*  if PDP-11 (or whatever), they were already 16 bits  */
  41. typedef int INT;
  42. #endif
  43.  
  44. struct _sqleaf {/* Decoding tree */
  45. INT _children[2];/* left, right */
  46. };
  47. struct _sqleaf Dnode[NUMVALS - 1];
  48.  
  49. INT early_exit = 0;
  50. INT lastchar = '\n';/* controls whether we need an extra nl after file */
  51. FILE *infile;
  52. char stobuf[BUFSIZ];/* use buffered output for efficiency */
  53.  
  54. INT Bpos;/* last bit position read */
  55. INT Curin;/* last byte value read */
  56. INT Repct;/* Number of times to retirn value */
  57. INT Value;/* current byte value or EOF */
  58.  
  59. INT getcr(), getuhuff();
  60.  
  61. snextfil()
  62. {
  63. signal(SIGQUIT, snextfil);
  64. ++early_exit;
  65. }
  66.  
  67. main(p_argc, p_argv)
  68. INT p_argc;
  69. char **p_argv;
  70. {
  71. char file[PATHLEN];
  72. register INT c, d, x;
  73.  
  74.  
  75. if (signal(SIGQUIT, snextfil)==SIG_IGN)
  76. signal(SIGQUIT, SIG_IGN);
  77. setbuf(stdout, stobuf);
  78. setbuf(stderr, 0);
  79.  
  80. if (p_argc < 2) {
  81. fprintf(stderr, "Usage: type file ...\n");
  82. exit(1);
  83. }
  84.  
  85. for (x = 1;x < p_argc;++x) {
  86. if(early_exit || lastchar != '\n')
  87. printf("\n");
  88. d= 39 - strlen(p_argv[x]);
  89. for (c=d; --c>=0 ;)
  90. putchar('=');
  91. printf(" %s ",p_argv[x]);
  92. for (c=d; --c>=0 ;)
  93. putchar('=');
  94. putchar('\n');
  95. fflush(stdout);
  96. early_exit = 0;
  97. switch (catvalid(file, p_argv[x])) {
  98. case 'q':
  99. switch (qsend(file)) {
  100. case ERROR:
  101. break;
  102. case 'a':
  103. send_text(file);
  104. }
  105. break;
  106. case 'a':
  107. send_text(file); break;
  108. case 'x':
  109. break;
  110. }
  111. }
  112. return (OK);
  113. }
  114.  
  115. send_text(file)
  116. char *file;
  117. {
  118. register INT c, lc;
  119.  
  120. while( ((c = getc(infile)) != EOF) && c != CPMEOF && (!early_exit) )
  121. putchar(lc=c);
  122. lastchar=c;
  123. fclose(infile);
  124. fflush(stdout);
  125. return (OK);
  126. }
  127.  
  128. catvalid(pname, name)
  129. char *pname;
  130. char *name;
  131. {
  132. if((infile=fopen(name, "r"))==NULL) {
  133. fprintf(stderr, "type: Can't open %s\n", name);
  134. return ERROR;
  135. }
  136. strcpy(pname, name);
  137. return ('q');
  138. }
  139.  
  140. /*
  141. The following code is primarily from typesq.c and utr.c.  Typesq
  142. is a modification of USQ by Dick Greenlaw.  Those modifications (usq
  143. to typesq) were made by Bob Mathias, I am responsible for the butchery
  144. done to make it work with cat.
  145.  
  146. */
  147.  
  148. qsend(fname)
  149. char *fname;
  150. {
  151. register INT i, c, lc;
  152. register char *p;
  153. register INT numnodes;/* size of decoding tree */
  154. char origname[PATHLEN];/* Original file name */
  155.  
  156. init_cr(); init_huff();
  157.  
  158. if(portgetw(infile) != RECOGNIZE) {/* Process header */
  159. rewind(infile);
  160. return 'a';/* not squeezed after all */
  161. }
  162. portgetw(infile);/* discard checksum */
  163. p = origname;/* Get original file name */
  164. do {/* send it to array */
  165. *p = getc(infile);
  166. } while(*p++ != '\0');
  167.  
  168. numnodes = portgetw(infile);
  169. if(numnodes < 0 || numnodes >= NUMVALS) {
  170. fprintf(stderr, "%s has invalid decode tree size\n", fname);
  171. fclose(infile);
  172. return ERROR;
  173. }
  174. /* Initialize for possible empty tree (SPEOF only) */
  175. Dnode[0]._children[0] = -(SPEOF + 1);
  176. Dnode[0]._children[1] = -(SPEOF + 1);
  177.  
  178. for(i = 0; i < numnodes; ++i) {/* Get decoding tree from file */
  179. Dnode[i]._children[0] = portgetw(infile);
  180. Dnode[i]._children[1] = portgetw(infile);
  181. }
  182. /* Get translated output bytes and write file */
  183. printf("\n%s -> %s\n\n",fname,origname);
  184. while( ((c = getcr(infile)) != EOF) && c != CPMEOF && (!early_exit) )
  185. putchar(lc=c);
  186. lastchar=lc;
  187. fclose(infile);
  188. fflush(stdout);
  189. return OK;
  190. }
  191. /*** from utr.c - */
  192. /* initialize decoding functions */
  193.  
  194. init_cr()
  195. {
  196. Repct = 0;
  197. }
  198.  
  199. init_huff()
  200. {
  201. Bpos = 99;/* force initial read */
  202. }
  203.  
  204. /* Get bytes with decoding - this decodes repetition,
  205.  * calls getuhuff to decode file stream into byte
  206.  * level code with only repetition encoding.
  207.  *
  208.  * The code is simple passing through of bytes except
  209.  * that DLE is encoded as DLE-zero and other values
  210.  * repeated more than twice are encoded as value-DLE-count.
  211.  */
  212.  
  213. INT
  214. getcr()
  215. {
  216. register INT c;
  217.  
  218. if(Repct > 0) {
  219. /* Expanding a repeated char */
  220. --Repct;
  221. return Value;
  222. } else {
  223. /* Nothing unusual */
  224. if((c = getuhuff()) != DLE) {
  225. /* It's not the special delimiter */
  226. Value = c;
  227. if(Value == EOF)
  228. Repct = LARGE;
  229. return Value;
  230. } else {
  231. /* Special token */
  232. if((Repct = getuhuff()) == 0)
  233. /* DLE, zero represents DLE */
  234. return DLE;
  235. else {
  236. /* Begin expanding repetition */
  237. Repct -= 2;/* 2nd time */
  238. return Value;
  239. }
  240. }
  241. }
  242. }
  243. /* Decode file stream INTo a byte level code with only
  244.  * repetition encoding remaining.
  245.  */
  246.  
  247. INT
  248. getuhuff()
  249. {
  250. register INT i;
  251. register INT bitval;
  252.  
  253. /* Follow bit stream in tree to a leaf*/
  254. i = 0;/* Start at root of tree */
  255. do {
  256. if(++Bpos > 7) {
  257. if((Curin = getc(infile)) == ERROR)
  258. return ERROR;
  259. Bpos = 0;
  260. /* move a level deeper in tree */
  261. i = Dnode[i]._children[1 & Curin];
  262. } else
  263. i = Dnode[i]._children[1 & (Curin >>= 1)];
  264. } while(i >= 0);
  265.  
  266. /* Decode fake node index to original data value */
  267. i = -(i + 1);
  268. /* Decode special endfile token to normal EOF */
  269. i = (i == SPEOF) ? EOF : i;
  270. return i;
  271. }
  272. /*
  273.  * Machine independent getw which always gets bytes in the same order
  274.  *  as the CP/M version of SQ wrote them
  275.  */
  276. portgetw(f)
  277. FILE *f;
  278. {
  279. register INT c;
  280.  
  281. c = getc(f)&0377;
  282. return c + (getc(f)<<8);
  283. }
  284.